/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.qframe.client.render;

import org.qframe.client.util.ContentHelper;
import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.RootPanel;
import java.util.ArrayList;
import org.qframe.client.error.TemplateConfigError;
import org.qframe.client.gwtcustom.QuickletHTMLPanel;
import org.qframe.client.quicklet.beans.Quicklet;
import org.qframe.client.quicklet.QuickletFactory;
import org.qframe.client.quicklet.QuickletLoader;
import org.qframe.client.quicklet.beans.RenderedQuicklet;
import org.qframe.client.quicklet.beans.RenderedSlot;
import org.qframe.client.quicklet.beans.Slot;

/**
 * The engine that does the actual Rendering of quicklets on the DOM.
 *
 * @author gprasad
 */
public class RenderEngine implements IContentLoadCallBack {

    private QuickletLoader qLoader = new QuickletLoader();
    private ArrayList<RenderingPayLoad> processQueue = new ArrayList<RenderingPayLoad>();

    private boolean isAnythingBeingProcessed() {
        return processQueue.size() > 0;
    }

    private void markProcessing(RenderingPayLoad pl) {
        processQueue.add(pl);
    }

    private void markProcessed(RenderingPayLoad pl) {
        processQueue.remove(pl);
        if (!isAnythingBeingProcessed()) {
            finished();
        }
    }

    private void finished() {
        DomUtils.dumpHtml();
    }

    static final class RenderingPayLoad {

        private RenderedQuicklet containerQicklet;
        private Slot containerSlot;
        private Quicklet quickletToRender;
        private Element slotDomElement;

        public RenderingPayLoad(Slot containerSlot, Quicklet quickletToRender, RenderedQuicklet containerQicklet) {
            this.containerSlot = containerSlot;
            this.quickletToRender = quickletToRender;
            this.containerQicklet = containerQicklet;
            this.slotDomElement = this.containerQicklet.getHtmlPanel().getElementById(this.containerSlot.getSlotId());

        }

        public RenderingPayLoad(RenderedSlot containerSlot, Quicklet quickletToRender) {
            this(containerSlot,
                    quickletToRender,
                    containerSlot.getParentQuicklet());
        }

        public void clearSlot() {
            if (slotDomElement != null) {
                slotDomElement.setInnerHTML("");
            }
        }

        public void showLoading() {
            if (slotDomElement != null) {
                slotDomElement.setInnerHTML("Loading ...");
            }
        }
    }

    public RenderEngine() {
        QuickletFactory.init();
    }

    public void render() {


        RenderedQuicklet welcomeQuicklet = DomUtils.renderWelcomeQuicklet();

        ArrayList<Slot> slotTags = DomUtils.getSlots(RootPanel.get());
        for (Slot slot : slotTags) {
            render(new RenderingPayLoad(slot, slot.getDefaultQuicklet(), welcomeQuicklet));
        }

    }

    public void render(RenderedSlot slot, Quicklet quicklet) {

        render(new RenderingPayLoad(slot, quicklet));
    }

    private void render(RenderingPayLoad pl) {

        String quickletPath = pl.quickletToRender.getPath();
        markProcessing(pl);
        pl.showLoading();
        ContentHelper.load(quickletPath, this, pl);
    }

    public void onContentResponse(String response, Object payload, boolean isError) {

        RenderingPayLoad renderingPayLoad = (RenderingPayLoad) payload;
        renderingPayLoad.clearSlot();

        RenderedSlot containerRenderedSlot = new RenderedSlot(renderingPayLoad.containerSlot, renderingPayLoad.containerQicklet);

        QuickletHTMLPanel panel = DomUtils.createQuickletHtmlPanel(renderingPayLoad.quickletToRender, response, containerRenderedSlot);
        //renderingPayLoad.containerQicklet.getHtmlPanel().addAndReplaceElement(panel, slotId);
        renderingPayLoad.containerQicklet.getHtmlPanel().add(panel, containerRenderedSlot.getRenderedSlotId());

        RenderedQuicklet currentRenderedQuicklet = new RenderedQuicklet(renderingPayLoad.quickletToRender, panel, containerRenderedSlot);

        initHandler(panel, renderingPayLoad, currentRenderedQuicklet);

        RenderedQuicklet parentForNewChildren = currentRenderedQuicklet;

        ArrayList<Slot> childSlots = DomUtils.getSlots(panel);

        for (Slot slot : childSlots) {

            RenderingPayLoad childRenderingPayload = new RenderingPayLoad(slot, slot.getDefaultQuicklet(), parentForNewChildren);
            render(childRenderingPayload);
        }

        markProcessed(renderingPayLoad);

    }

    private void initHandler(HTMLPanel panel, RenderingPayLoad renderingPayLoad, RenderedQuicklet renderedQuicklet) throws TemplateConfigError {
        qLoader.initializeQHandler(renderedQuicklet);
    }
}
